package cn.lg.soar.core.manager;

import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 权限验证器
 * @author luguoxiang
 * @date 2021/8/23
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface IPermitValidator {

    IPermitValidator EMPTY = x -> false;

    /**
     * 验证权限
     * @param permit
     * @return
     */
    boolean has(String permit);

    /**
     * 构建权限验证器
     * @param permits
     * @return
     */
    static IPermitValidator build(Collection<String> permits) {
        if (CollectionUtils.isEmpty(permits)) {
            return EMPTY;
        }
        // 分类
        Set<String> patterns = new HashSet<>(permits.size());
        Set<String> uris = new HashSet<>(permits.size());
        for (String x : permits) {
            if (x.contains("*")) {
                patterns.add(x);
            } else {
                uris.add(x);
            }
        }

        // 按需生成实现类（策略模式）
        if (CollectionUtils.isEmpty(patterns)) {
            // 该角色只有精确匹配权限
            return new EqualValidator(uris);
        }
        if (CollectionUtils.isEmpty(uris)) {
            // 该角色只有模糊匹配权限
            return new MatchValidator(patterns.toArray(new String[0]));
        }
        // 该角色既有全匹配权限，也有模糊匹配权限
        return new Validator(uris, patterns.toArray(new String[0]));
    }

    /**
     * 多匹配模式(精确与模糊)
     */
    class Validator implements IPermitValidator {
        /**
         * 精确匹配
         */
        private final Set<String> permits;
        private final static AntPathMatcher MATCHER = new AntPathMatcher();
        /**
         * 模糊匹配
         */
        private final String[] patterns;
        public Validator(Set<String> permits, String[] patterns) {
            this.permits = permits;
            this.patterns = patterns;
        }

        @Override
        public boolean has(String permit) {
            if (this.permits.contains(permit)) {
                return true;
            }
            for (String pattern : patterns) {
                if (MATCHER.match(pattern, permit)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 模糊匹配
     */
    class MatchValidator implements IPermitValidator {

        private final String[] patterns;
        private final static AntPathMatcher MATCHER = new AntPathMatcher();

        public MatchValidator(String[] patterns) {
            this.patterns = patterns;
        }

        @Override
        public boolean has(String permit) {
            for (String pattern : patterns) {
                if (MATCHER.match(pattern, permit)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 精确匹配
     */
    class EqualValidator implements IPermitValidator {

        private final Set<String> permits;

        public EqualValidator(Set<String> permits) {
            this.permits = permits;
        }

        @Override
        public boolean has(String permit) {
            return this.permits.contains(permit);
        }
    }

}
